﻿// <copyright file="AbstractComposite.cs" company="graphs-dotnet">
// Copyright 2009 Dmitri Pavlenkov
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at 
// 
// http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License. 
//
// THIRD PARTY LICENSES
//
// This file's code annotations follow David Betz' Code Annotation Format.
// The orignal can be obtained at
//
// http://www.netfxharmonics.com/document/code/format
//
// </copyright>
// <summary>
// AbstractComposite.cs file.
// </summary>
//+


namespace Graphs.Core
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  //+
  
  /// <inheritdoc/>
  /// <summary>
  /// Abstract base for composite implementations.
  /// </summary>
  public abstract class AbstractComposite<E> : IComposite<E>
    where E : class
  {
    //+
    //- #EdgeMap -//
    /// <summary>
    /// Stores edges and nodes.
    /// </summary>
    protected Dictionary<E, AbstractComposite<E>> EdgeMap { get; set; }

    //- @Root -//
    /// <inheritdoc cref="P:Graphs.Core.IGraph`1.Root"/>
    public IVertex<E> Root { get; protected set; }
    
    //- @Indexer -//
    /// <summary>
    /// Follow method wrapper.
    /// </summary>
    public virtual AbstractComposite<E> this[E edge] 
    {
      get
      {
        return Follow(edge) as AbstractComposite<E>;
      }
    }
    
    /// <summary>
    /// Follow the edge path recursively.
    /// </summary>
    public virtual AbstractComposite<E> this[IEnumerable<E> path]
    {
      get
      {
        E current=path.FirstOrDefault();
        if(current==null)
        {
          return this;
        }
        else
        {
          return this[current][path.Skip(1)];
        }
      }
    }
    
    //+
    //- @Ctor -//
    /// <summary>
    /// Creates new <c>composite</c>.
    /// </summary>
    public AbstractComposite()
    {
      Root=this;
      EdgeMap=new Dictionary<E, AbstractComposite<E>>();
    }
    
    //+
    //- @Follow -//
    /// <inheritdoc cref="M:Graphs.Core.INode`1.Follow(`0)"/>
    public abstract IVertex<E> Follow(E edge);

  }
}
